home *** CD-ROM | disk | FTP | other *** search
- /*
- Truchet Tiling - by John Jeppson.
-
- This source code is in the public domain.
- Written in MPW C.
-
- This program is an MPW Tool which implements Truchet Tiling
- as described in "Computer Recreations" by A.K.Dewdney in
- Scientific American, July 1989.
-
- From the MPW Worksheet execute:
-
- Tile n
-
- where "n" is an integer [0..100] which represents the percentage
- bias for an otherwise random test array, as described in the
- same article. A value of 0 yields a completely random array.
-
- After the tiling is drawn you will hear a SysBeep.
- You may print the completed tiling by pressing "p".
- Return to the shell with the close box.
- */
-
- #include <Types.h>
- #include <Windows.h>
- #include <Memory.h>
- #include <Printing.h>
- #include <Fonts.h>
- #include <Resources.h>
- #include <OSUtils.h>
-
- #define TruchetRadius 5 /* radius of tiling curves */
-
- #define windowTop 40
- #define windowLeft 4
- #define windowHeight 250
- #define windowWidth 400
- #define windowTitle "\pTruchet Tiling"
-
- #define maxX ( windowWidth / (TruchetRadius * 2) + 1 )
- #define maxY ( windowHeight / (TruchetRadius * 2) + 1 )
-
- #define nil 0L
-
-
- /**** globals ****/
-
- long bias;
- Boolean array[maxX][maxY];
- WindowPtr display;
- Boolean alreadyDrawn;
- BitMap offScreen;
-
-
- /**** the tiling procedures ****/
-
- void TruchetA(short x, short y, short radius)
- {
- Rect r;
-
- SetRect(&r, x - radius, y - radius, x + radius, y + radius);
- FrameArc(&r, 90, 90);
- OffsetRect(&r, radius * 2, radius * 2);
- FrameArc(&r, 270, 90);
- }
-
- void TruchetB(short x, short y, short radius)
- {
- Rect r;
-
- SetRect(&r, x + radius, y - radius, x + (radius * 3), y + radius);
- FrameArc(&r, 180, 90);
- OffsetRect(&r, - (radius * 2), radius * 2);
- FrameArc(&r, 0, 90);
- }
-
- void TruchetTile(
- short rows,
- short cols,
- short radius, /* radius of Truchet tiling curves */
- Boolean (*fetch)(short x, short y) ) /* called to get orientation */
- {
- short i,j;
-
- PenNormal();
- for ( i = 0; i < cols; ++i )
- for ( j = 0; j < rows; ++j )
- if ( (*fetch)(i,j) )
- TruchetA(i * radius * 2, j * radius * 2, radius);
- else
- TruchetB(i * radius * 2, j * radius * 2, radius);
- }
-
-
-
- /**** data manipulation for this example ****/
-
-
- Boolean getValue(short x, short y)
- {
- return array[x][y];
- }
-
-
- void initArray()
- {
- short i, j, n;
- Boolean carry;
-
- for ( j = 0; j < maxY; ++j )
- {
- carry = false;
- for ( i = 0; i < maxX; ++i )
- {
- n = Random() % 100;
- if ( n >= bias )
- carry = ((n % 2) == 0);
- array[i][j] = carry;
- }
- }
- }
-
-
- void drawContents(WindowPtr w)
- {
- EraseRect(&(w->portRect));
-
- if ( alreadyDrawn )
- {
- CopyBits (&offScreen, &(display->portBits),
- &(offScreen.bounds), &(offScreen.bounds),
- srcCopy, nil);
- }
- else
- {
- TruchetTile (maxY, maxX, TruchetRadius, getValue);
- alreadyDrawn = true;
- CopyBits (&(display->portBits), &offScreen,
- &(offScreen.bounds), &(offScreen.bounds),
- srcCopy, nil);
- SysBeep(1);
- }
- }
-
-
- /**** generic tool stuff ****/
-
-
- void doUpdate(WindowPtr w)
- {
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(w);
- ClipRect(&(w->portRect));
- BeginUpdate(w);
- drawContents(w);
- EndUpdate(w);
- SetPort(savePort);
- }
-
-
- void makeOffScreen() /* set up offscreen bitmap to store image */
- {
- Size sizeOfOff;
- short offRowBytes;
-
- offRowBytes = (((windowWidth - 1) / 16) + 1) * 2;
- sizeOfOff = windowHeight * offRowBytes;
-
- offScreen.baseAddr = (QDPtr) NewPtr(sizeOfOff);
- offScreen.rowBytes = offRowBytes;
- SetRect(&(offScreen.bounds), 0, 0, windowWidth, windowHeight);
- }
-
-
- void makeWindow()
- {
- Rect bounds;
-
- SetRect(&bounds, windowLeft, windowTop, windowLeft + windowWidth, windowTop + windowHeight);
- display = NewWindow(nil, &bounds, windowTitle, true, noGrowDocProc, (WindowPtr) -1, true, 0L);
- }
-
-
- void printTile()
- {
- TPPrPort pport;
- THPrint hPrint;
- TPrStatus PrStatus;
- GrafPtr oldPort;
- Boolean notCancelled = true;
- Boolean drop;
-
- GetPort (&oldPort);
- PrOpen();
-
- SetFractEnable(true);
- SetFScaleDisable(true);
-
- hPrint = (THPrint) NewHandle(sizeof(TPrint));
- if (ResError())
- {
- printf ("Printing Error %d\n", ResError());
- SysBeep(1);
- PrClose();
- return;
- }
-
- drop = PrValidate(hPrint);
- notCancelled = PrJobDialog (hPrint);
-
- if (notCancelled)
- {
- pport = PrOpenDoc(hPrint, nil, nil);
- if ( PrError() == noErr )
- {
- PrOpenPage(pport, nil);
- if (PrError()==noErr)
- CopyBits (&offScreen, &(pport->gPort.portBits),
- &(offScreen.bounds), &(offScreen.bounds),
- srcCopy, nil);
- PrClosePage(pport);
- }
- PrCloseDoc(pport);
- }
- if ( ((**hPrint).prJob.bJDocLoop == bSpoolLoop)
- && (PrError() == noErr) )
- PrPicFile (hPrint, nil, nil, nil, &PrStatus);
-
- SetFractEnable(false);
- SetFScaleDisable(false);
-
- PrClose();
-
- SetPort (oldPort);
- }
-
- void mainLoop()
- {
- Boolean done = false;
- EventRecord theEvent;
- WindowPtr whichWindow;
- short part;
-
- while ( !done )
- {
- if ( GetNextEvent(everyEvent, &theEvent) )
- {
- switch ( theEvent.what )
- {
- case updateEvt:
- doUpdate(display);
- break;
-
- case mouseDown:
- part = FindWindow(theEvent.where, &whichWindow);
- if ( (whichWindow == display) && (part == inGoAway) )
- done = true;
- break;
-
- case keyDown:
- if ( 'p' == (theEvent.message & charCodeMask) )
- printTile();
- break;
- }
- }
- }
- }
-
-
- void cleanUp()
- {
- DisposeWindow(display);
- DisposPtr((Ptr) offScreen.baseAddr);
- }
-
-
- int main (
- int argc, /* number of arguments */
- char *argv[], /* pointer to array of argument strings */
- char *envp[]) /* pointer to array of variable definitions */
- {
- #pragma unused (envp)
-
- InitGraf((Ptr) &qd.thePort);
- SetFScaleDisable(true);
- InitCursor();
-
- if ( argc != 2 )
- {
- printf ("### Wrong Number of Parameters ###\n");
- return 2;
- }
- bias = atol(argv[1]);
-
- alreadyDrawn = false;
-
- makeOffScreen();
- initArray();
- makeWindow();
- mainLoop();
- cleanUp();
-
- return 0;
- }
-